package rongqi;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Queue;
import java.util.Spliterator;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;

import static java.util.concurrent.ThreadLocalRandom.current;

/**
 * LinkedList试验
 * @author ben
 * @date 2021-10-28 11:49:16 CST
 */
public class TestLinkedList {

	public static void main(String[] args) {
//		test1AsList();
		
//		test2AsQueue();
		
		test3AsDeque();
	}
	
	/**
	 * LinkedList as List
	 * @author ben
	 * @date 2021-10-28 11:49:03 CST
	 */
	private static void test1AsList() {
		List<Integer> lt = new LinkedList<>();
		
		// add
		IntStream.range(0, 10).forEach(el->{
			lt.add(el);
		});
		
		PKG_RONGQI.pt(lt);
		
		// addAll
		List<Integer> lt2 = new LinkedList<>();
		lt2.addAll(lt);
		PKG_RONGQI.pt(lt2);
		lt2 = null;
		
		// get
		PKG_RONGQI.pt("遍历-foreach：");
		for (Integer el : lt) {
			PKG_RONGQI.pt(el);
		}
		
		StringBuilder sb = new StringBuilder();
		
		PKG_RONGQI.pt("遍历-Iterator：");
		Iterator<Integer> it = lt.iterator();
		while (it.hasNext()) {
			sb.append(it.next()).append(" ");
		}
		PKG_RONGQI.pt(sb);
		sb.setLength(0);
		
		PKG_RONGQI.pt("遍历-ListIterator：");
		ListIterator<Integer> lit = lt.listIterator();
		
		// 先后向遍历，再前向遍历
		PKG_RONGQI.pt("遍历-前向：");
		lit.next();
		lit.next();
		lit.next();
		while (lit.hasPrevious()) {
			int el = lit.previous();
			sb.append(el).append(" ");
		}
		PKG_RONGQI.pt(sb);
		sb.setLength(0);
		
		PKG_RONGQI.pt("ListIterator#forEachRemaining:");
		lit.forEachRemaining(el->{
			sb.append(el).append(" ");
		});
		PKG_RONGQI.pt(sb);
		sb.setLength(0);
		
		// contains
		PKG_RONGQI.pt("contains: \n" + lt.contains(100));
		PKG_RONGQI.pt(lt.contains(1));
		PKG_RONGQI.pt(lt.contains(-1));
		PKG_RONGQI.pt(lt.contains(9));
		
		// 1414+
		
		// replaceAll
		lt.replaceAll(el->{
			return el + 10;
		});
		PKG_RONGQI.pt("replaceAll:\nlt=" + lt);
		
		// retainAll
		List<Integer> lt3 = new ArrayList<Integer>();
		lt3.add(1);
		lt3.add(11);
		lt3.add(12);
		lt3.add(123);
		PKG_RONGQI.pt("retainAll:\nlt3.1=" + lt3);
		lt.retainAll(lt3);
		PKG_RONGQI.pt("lt3.2=" + lt3);
		PKG_RONGQI.pt("lt=" + lt);
		
		// 错误：remove(int)
		// IndexOutOfBoundsException
//		lt.remove(11);
//		lt.remove(12);
		// 正确：remove(Object)
		lt.remove(Integer.valueOf(11));
		lt.remove(Integer.valueOf(12));
		PKG_RONGQI.pt("remove:\nlt=" + lt);
		
		lt3.clear();
		PKG_RONGQI.pt("clear:\nlt3=" + lt3);
		
		// 初始化
		IntStream.range(0, 10).forEach(lt::add);
		PKG_RONGQI.pt("new lt=" + lt);
		
		// 不熟，TODO
		Spliterator<Integer> sp = lt.spliterator();
		sb.append(sp.characteristics() + ", ");
		sb.append(String.format("0x%02x", sp.characteristics()) + ", ");
		sb.append(sp.estimateSize() + ", ");
		sb.append(sp.getExactSizeIfKnown() + ", ");
		PKG_RONGQI.pt("Spliterator: " + sb);
		sb.setLength(0);
		
		IntStream.range(0, 10).forEach(el->{
			lt.add(ThreadLocalRandom.current().nextInt(20));
		});
		PKG_RONGQI.pt("new 2 lt=" + lt);
		sb.append(sp.characteristics() + ", ");
		sp = lt.spliterator();
		sb.append(String.format("0x%02x", sp.characteristics()) + ", ");
		PKG_RONGQI.pt("Spliterator 2: " + sb);
		sb.setLength(0);
		
		// 子串
		// 注意IndexOutOfBoundsException
		PKG_RONGQI.pt("子串：\nsub list =" + lt.subList(4, 19));
		
		// 排序
		lt.sort((e1,e2) -> {
			// 升序
//			return e1 - e2;
			// 降序
			return e2 - e1;
		});
		PKG_RONGQI.pt("排序：\nlt=" + lt);
	}
	
	/**
	 * LinkedList as Queue
	 * FIFO 先进先出，队尾添加，队头取数
	 * @author ben
	 * @date 2021-10-28 15:07:57 CST
	 */
	private static void test2AsQueue() {
		Queue<Integer> lq = new LinkedList<>();
		initColl(lq, true);
		
		// offer添加
		boolean o1 = lq.offer(123);
		PKG_RONGQI.pt("o1=" + o1 + ", lq=" + lq);

		// peek 取数 不影响Q
		PKG_RONGQI.pt("peek:\n" + lq.peek());
		PKG_RONGQI.pt(lq.peek());
		PKG_RONGQI.pt(lq.peek());
		PKG_RONGQI.pt("lq=" + lq);
		
		// element 取数 不影响Q
		PKG_RONGQI.pt("element:\n" + lq.element());
		PKG_RONGQI.pt(lq.element());
		PKG_RONGQI.pt(lq.element());
		PKG_RONGQI.pt("lq=" + lq);

		// poll 取数：删除元素
		PKG_RONGQI.pt("poll:\n" + lq.poll());
		PKG_RONGQI.pt(lq.poll());
		PKG_RONGQI.pt(lq.poll());
		PKG_RONGQI.pt("lq=" + lq);

		// remove 取数：删除元素
		PKG_RONGQI.pt("remove:\n" + lq.remove());
		PKG_RONGQI.pt(lq.remove());
		PKG_RONGQI.pt(lq.remove());
		PKG_RONGQI.pt("lq=" + lq);
		
		lq.clear();
		PKG_RONGQI.pt("清空 lq=" + lq);
		
		// 返回 null
		PKG_RONGQI.pt("peek 空lq：" + lq.peek());
		// NoSuchElementException
//		PKG_RONGQI.pt("element 空lq：" + lq.element());
		
		// 返回 null
		PKG_RONGQI.pt("poll 空lq：" + lq.poll());
		// NoSuchElementException
//		PKG_RONGQI.pt("remove 空lq：" + lq.remove());
		
		lq.offer(123);
		lq.add(321);
		lq.offer(123333);
		lq.add(321111);
		PKG_RONGQI.pt("new lq=" + lq);
		
		lq.forEach(System.out::println);
		
		PKG_RONGQI.pt("Iterator遍历：");
		Iterator<Integer> it = lq.iterator();
		it.forEachRemaining(el->{
			PKG_RONGQI.pt(el);
		});
	}

	/**
	 * LinkedList as Deque
	 * @author ben
	 * @date 2021-10-28 15:07:57 CST
	 */
	private static void test3AsDeque() {
		Deque<Integer> ldq = new LinkedList<>();
		
		ldq.add(1);
		ldq.addFirst(2);
		ldq.addLast(3);
		PKG_RONGQI.pt("ldq=" + ldq); // [2, 1, 3]
		
		StringBuilder sb = new StringBuilder();

		Iterator<Integer> it = ldq.iterator();
		while (it.hasNext()) {
			int el = it.next();
			sb.append(el).append(" ");
		}
		PKG_RONGQI.pt("ldq.iterator() sb=" + sb); // 2 1 3
		sb.setLength(0);
		
		it = ldq.descendingIterator();
		while (it.hasNext()) {
			int el = it.next();
			sb.append(el).append(" ");
		}
		PKG_RONGQI.pt("ldq.descendingIterator() sb=" + sb); // 3 1 2
		sb.setLength(0);
		
		// get element peek
		PKG_RONGQI.pt(ldq.getFirst() + ", " + ldq.getLast());
		PKG_RONGQI.pt(ldq.getFirst() + ", " + ldq.getLast());
		PKG_RONGQI.pt(ldq.element() + ", " + ldq.element());
		PKG_RONGQI.pt(ldq.peek() + ", " + ldq.peek());
		PKG_RONGQI.pt(ldq.peekFirst() + ", " + ldq.peekLast());
		PKG_RONGQI.pt("ldq=" + ldq);
		
		// remove  3个元素 删除4次
		PKG_RONGQI.pt("remove: \n" + ldq.remove());
		PKG_RONGQI.pt(ldq.remove());
		PKG_RONGQI.pt(ldq.remove());
		// NoSuchElementException
//		PKG_RONGQI.pt(ldq.remove());
		PKG_RONGQI.pt("ldq=" + ldq);
		
		initColl(ldq, true);
		PKG_RONGQI.pt("new ldq=" + ldq);
//		ldq.forEach(el->{
//			// java.util.ConcurrentModificationException
//			ldq.remove();
//		});
		// 异常：10个元素，但是，ldq等于5！循环条件用了 
		// ldq.size()，是动态的，故没有删除完毕
		PKG_RONGQI.pt("ldq.size=" + ldq.size());
		int ldqSize = ldq.size();
		for (int i=0; i<ldqSize; i++) {
			PKG_RONGQI.pt("i=" + i);
			int eli = ldq.removeFirst();
			sb.append(eli).append(" ");
		}
		PKG_RONGQI.pt("removeFirst sb=" + sb);
		sb.setLength(0);
		
		PKG_RONGQI.pt("removeFirst ldq=" + ldq);
		// NoSuchElementException
//		int el = ldq.remove();
//		PKG_RONGQI.pt("removed 2 ldq=" + ldq + ", el=" + el);

		PKG_RONGQI.pt("ldq.size=" + ldq.size());

		initColl(ldq, true);
		PKG_RONGQI.pt("new ldq=" + ldq);
		
		ldqSize = ldq.size();
		for (int i=0; i<ldqSize; i++) {
			int eli = ldq.removeLast();
			sb.append(eli).append(" ");
		}
		PKG_RONGQI.pt("removeLast sb=" + sb);
		sb.setLength(0);
		PKG_RONGQI.pt("removeLast ldq=" + ldq);
		
		initColl(ldq, true);
		PKG_RONGQI.pt("new ldq=" + ldq);
		ldqSize = ldq.size();
		for (int i=0; i<ldqSize; i++) {
			int eli = ldq.pollLast();
			sb.append(eli).append(" ");
		}
		// null
		Integer el = ldq.pollLast();
		sb.append(el).append(" ");
		Integer el1 = ldq.pollLast();
		sb.append(el1).append(" ");
		PKG_RONGQI.pt("pollLast sb=" + sb);
		sb.setLength(0);
		PKG_RONGQI.pt("pollLast ldq=" + ldq);

		initColl(ldq, false);
		PKG_RONGQI.pt("new ldq=" + ldq);
		ldq.removeFirstOccurrence(3);
		PKG_RONGQI.pt("removeFirstOccurrence(3) ldq=" + ldq);
		
		//
		// Stack 栈 后进先出
		// 两个方法：pop, push
		
		// pop 出栈
		int ldqlen = ldq.size();
		for (int i=0; i<ldqlen; i++) {
			Integer popret = ldq.pop();
			PKG_RONGQI.pt(i + "、popret=" + popret);
		}
		PKG_RONGQI.pt("ldq=" + ldq + ", size=" + ldq.size()); // [], 0
		
		// 空栈 异常 java.util.NoSuchElementException
//		ldq.pop();
		
		// 入栈
		ldqlen += 10;
		for (int i=0; i<ldqlen; i++) {
			ldq.push(i);
		}
		PKG_RONGQI.pt("after pushed ldq=" + ldq); // 19, 18, ..., 0
		
		PKG_RONGQI.pt("pop 1=" + ldq.pop()); // 19
		PKG_RONGQI.pt("pop 2=" + ldq.pop()); // 18
	}
	
	/**
	 * 初始化
	 * @author ben
	 * @date 2021-10-28 15:20:04 CST
	 * @param coll
	 * @param order
	 */
	private static void initColl(Collection<Integer> coll, boolean order) {
		IntStream.range(0, 10).forEach(el->{
			if (order) {
				coll.add(el);
			} else {
				coll.add(current().nextInt(10));
			}
		});
	}

}
